package com.atkxp.sys.service.impl;

import com.alibaba.fastjson2.JSON;
import com.atkxp.sys.entity.Menu;
import com.atkxp.sys.entity.Role;
import com.atkxp.sys.entity.User;
import com.atkxp.sys.entity.UserRole;
import com.atkxp.sys.mapper.UserMapper;
import com.atkxp.sys.mapper.UserRoleMapper;
import com.atkxp.sys.service.IMenuService;
import com.atkxp.sys.service.IUserService;
import com.atkxp.sys.utils.JwtUtils;
import com.atkxp.sys.utils.RedisUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author kxp
 * @since 2023-08-26
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    public PasswordEncoder passwordEncoder;

    @Autowired
    public RedisUtils redisUtils;

    @Autowired
    public JwtUtils jwtUtils;

    @Autowired
    public UserRoleMapper userRoleMapper;

    @Autowired
    public IMenuService menuService;
    @Override
    public Map<String, Object> login(User user) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, user.getUsername());
//        wrapper.eq(User::getPassword, user.getPassword());

        User login = this.baseMapper.selectOne(wrapper);
        if(login != null && passwordEncoder.matches(user.getPassword(), login.getPassword())) {
//            String key = "user:" + UUID.randomUUID();

            login.setPassword(null);
            String key = jwtUtils.createToken(login);
            redisUtils.setex(key, login, 1800);

            Map<String, Object> data = new HashMap<>();
            data.put("token", key);

            return data;
        }
        return null;
    }

    @Override
    public Map<String, Object> getUserInfo(String token) {
        Object obj = redisUtils.get(token);
        if(obj != null) {
//            User login = (User) obj;
            User login = JSON.parseObject(JSON.toJSONString(obj), User.class);
            Map<String, Object> data = new HashMap<>();
            data.put("name", login.getUsername());
            data.put("avatar", login.getAvatar());

            List<String> roleList = this.getBaseMapper().getRoleNamesByUserId(login.getId());
            data.put("roles", roleList);

            List<Menu> menuList = menuService.getMenuListByUserId(login.getId());
            data.put("menuList", menuList);
//            System.out.println(menuList);
            return data;
        }
        return null;
    }

    @Override
    public void logout(String token) {
        redisUtils.del(token);
    }

    @Override
    @Transactional
    public void addUser(User user) {
        this.baseMapper.insert(user);

        List<Integer> roleIdList = user.getRoleIdList();

        if(roleIdList != null) {
            for(Integer roleId: roleIdList) {
                userRoleMapper.insert(new UserRole(null, user.getId(), roleId));
            }
        }
    }

    @Override
    public User getUserById(Integer id) {
        User user = this.baseMapper.selectById(id);

        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId, id);
        List<UserRole> userRoleList = userRoleMapper.selectList(wrapper);

        List<Integer> roleIdList = userRoleList.stream().map(userRole -> {return userRole.getRoleId();}).collect(Collectors.toList());
        user.setRoleIdList(roleIdList);
        return user;
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        this.baseMapper.updateById(user);

        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId, user.getId());
        userRoleMapper.delete(wrapper);

        List<Integer> roleIdList = user.getRoleIdList();

        if(roleIdList != null) {
            for(Integer roleId: roleIdList) {
                userRoleMapper.insert(new UserRole(null, user.getId(), roleId));
            }
        }

    }

    @Override
    @Transactional
    public void deleteUserById(Integer id) {
        this.baseMapper.deleteById(id);

        LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserRole::getUserId, id);
        userRoleMapper.delete(wrapper);
    }
}
